# -*- coding: utf-8 -*-
# created on 2016/6/23


from mathsolver.functions.sympy_utils import safe_degree
from sympy import Poly
from mathsolver.functions.fangcheng.erci import ErCi003
from mathsolver.functions.base import *


# 求二次函数的顶点式
class HanShuErCiDingDianShi(BaseFunction):
    def solver(self, *args):
        f1 = Symbol("y")
        f2 = args[0].expression.simplify()
        assert str(f1) == "y", "Not a function!"
        symbol = default_symbol(f2)
        if safe_degree(f2, symbol) == 2:
            f2_poly = Poly(f2.as_expr(), symbol)
            a, b, c = f2_poly.all_coeffs()
            f2_x = f2_poly.args[0] - c
            if a == 1:
                if c > 0:
                    self.steps.append(
                        ["", "%s = (%s + %s) - %s + %s" % (new_latex(f1), new_latex(f2_x), new_latex((b / 2) ** 2),
                                                           new_latex((b / 2) ** 2), new_latex(c))])
                elif c == 0:
                    self.steps.append(
                        ["", "%s = (%s + %s) - %s" % (new_latex(f1), new_latex(f2_x), new_latex((b / 2) ** 2),
                                                      new_latex((b / 2) ** 2))])
                elif c < 0:
                    self.steps.append(
                        ["", "%s = (%s + %s) - %s - %s" % (new_latex(f1), new_latex(f2_x), new_latex((b / 2) ** 2),
                                                           new_latex((b / 2) ** 2), new_latex(-c))])
                if b > 0:
                    if -(b / 2) ** 2 + c > 0:
                        self.steps.append(
                            ["", "%s = (%s + %s)**2 + %s" % (new_latex(f1), new_latex(symbol), new_latex(b / 2),
                                                             new_latex(-(b / 2) ** 2 + c))])
                    elif -(b / 2) ** 2 + c == 0:
                        self.steps.append(
                            ["", "%s = (%s + %s)**2" % (new_latex(f1), new_latex(symbol), new_latex(b / 2))])
                    elif -(b / 2) ** 2 + c < 0:
                        self.steps.append(
                            ["", "%s = (%s + %s)**2 - %s" % (new_latex(f1), new_latex(symbol), new_latex(b / 2),
                                                             new_latex(-(-(b / 2) ** 2 + c)))])
                elif b < 0:
                    if -(b / 2) ** 2 + c > 0:
                        self.steps.append(
                            ["", "%s = (%s - %s)**2 + %s" % (new_latex(f1), new_latex(symbol), new_latex(-b / 2),
                                                             new_latex(-(b / 2) ** 2 + c))])
                    elif -(b / 2) ** 2 + c == 0:
                        self.steps.append(
                            ["", "%s = (%s - %s)**2" % (new_latex(f1), new_latex(symbol), new_latex(-b / 2))])
                    elif -(b / 2) ** 2 + c < 0:
                        self.steps.append(
                            ["", "%s = (%s - %s)**2 - %s" % (new_latex(f1), new_latex(symbol), new_latex(-b / 2),
                                                             new_latex(-(-(b / 2) ** 2 + c)))])
            else:
                if c > 0:
                    self.steps.append(
                        ["", "%s = %s * (%s) + %s" % (new_latex(f1), new_latex(a), new_latex(f2_x / a), new_latex(c))])
                    self.steps.append(
                        ["", "%s = %s * (%s + %s) - %s + %s" % (new_latex(f1), new_latex(a), new_latex(f2_x / a),
                                                                new_latex(b ** 2 / (4 * a ** 2)),
                                                                new_latex(b ** 2 / (4 * a)), new_latex(c))])
                elif c == 0:
                    self.steps.append(["", "%s = %s * (%s)" % (new_latex(f1), new_latex(a), new_latex(f2_x / a))])
                    self.steps.append(
                        ["", "%s = %s * (%s + %s) - %s" % (new_latex(f1), new_latex(a), new_latex(f2_x / a),
                                                           new_latex(b ** 2 / (4 * a ** 2)),
                                                           new_latex(b ** 2 / (4 * a)))])
                elif c < 0:
                    self.steps.append(
                        ["", "%s = %s * (%s) - %s" % (new_latex(f1), new_latex(a), new_latex(f2_x / a), new_latex(-c))])
                    self.steps.append(["", "%s = %s * (%s + %s) - %s - %s" % (
                    new_latex(f1), new_latex(a), new_latex(f2_x / a), new_latex(b ** 2 / (4 * a ** 2)),
                    new_latex(b ** 2 / (4 * a)), new_latex(-c))])
                if b > 0:
                    if (4 * a * c - b ** 2) / (4 * a) > 0:
                        self.steps.append(
                            ["", "%s = %s * (%s + %s)**2 + %s" % (new_latex(f1), new_latex(a), new_latex(symbol),
                                                                  new_latex(b / (2 * a)),
                                                                  new_latex((4 * a * c - b ** 2) / (4 * a)))])
                    elif (4 * a * c - b ** 2) / (4 * a) == 0:
                        self.steps.append(["", "%s = %s * (%s + %s)**2" % (
                        new_latex(f1), new_latex(a), new_latex(symbol), new_latex(b / (2 * a)))])
                    elif (4 * a * c - b ** 2) / (4 * a) < 0:
                        self.steps.append(
                            ["", "%s = %s * (%s + %s)**2 - %s" % (new_latex(f1), new_latex(a), new_latex(symbol),
                                                                  new_latex(b / (2 * a)),
                                                                  new_latex(-((4 * a * c - b ** 2) / (4 * a))))])
                elif b < 0:
                    if (4 * a * c - b ** 2) / (4 * a) > 0:
                        self.steps.append(
                            ["", "%s = %s * (%s - %s)**2 + %s" % (new_latex(f1), new_latex(a), new_latex(symbol),
                                                                  new_latex(-(b / (2 * a))),
                                                                  new_latex((4 * a * c - b ** 2) / (4 * a)))])
                    elif (4 * a * c - b ** 2) / (4 * a) == 0:
                        self.steps.append(["", "%s = %s * (%s + %s)**2" % (
                        new_latex(f1), new_latex(a), new_latex(symbol), new_latex(-(b / (2 * a))))])
                    elif (4 * a * c - b ** 2) / (4 * a) < 0:
                        self.steps.append(
                            ["", "%s = %s * (%s + %s)**2 - %s" % (new_latex(f1), new_latex(a), new_latex(symbol),
                                                                  new_latex(-(b / (2 * a))),
                                                                  new_latex(-((4 * a * c - b ** 2) / (4 * a))))])
            # constant1 = b / (2 * a)
            # dingdian_x = - constant1
            # dingdian_y = (4 * a * c - b ** 2) / (4 * a)
            # dingdian_f2 = a * (symbol + constant1) ** 2 + dingdian_y
            # self.steps.append(["", "将二次函数化为顶点式，得 %s = %s" % (latex(f1), latex(dingdian_f2))])
            self.label.add("将二次函数的化为顶点式")
        return self


# 求二次函数的顶点
class HanShuErCiDingDian(BaseFunction):
    def get_dingdian(self, f1, f2):
        symbol = default_symbol(f2)
        dingdian = []
        if safe_degree(f2, symbol) == 2:
            f2_poly = Poly(f2.as_expr(), symbol)
            a, b, c = f2_poly.all_coeffs()
            constant1 = b / (2 * a)
            dingdian_x = - constant1
            dingdian.append(dingdian_x)
            dingdian_y = (4 * a * c - b ** 2) / (4 * a)
            dingdian.append(dingdian_y)
            dingdian_f2 = a * (symbol + constant1) ** 2 + dingdian_y
            self.steps.append(["", "将二次函数化为顶点式，得 %s = %s" % (new_latex(f1), new_latex(dingdian_f2))])
            self.label.add("将二次函数的化为顶点式")
        return dingdian

    def solver(self, *args):
        f1 = Symbol("y")
        f2 = args[0].expression
        assert str(f1) == "y", "Not a function!"

        dingdian = self.get_dingdian(f1, f2)
        point = BasePoint([dingdian[0], dingdian[1]])
        self.steps.append(["", "顶点坐标为%s" % point.printing()])
        self.output.append(point)
        self.label.add("求二次函数的顶点")
        return self


# 求二次函数的对称轴
class HanShuErCiDuiChenZhou(HanShuErCiDingDian):
    def solver(self, *args):
        f1 = Symbol("y")
        f2 = args[0].expression

        symbol = default_symbol(f2)
        dingdian = self.get_dingdian(f1, f2)
        self.steps.append(["", "对称轴为%s" % self.output_eq([symbol, dingdian[0]])])
        self.output.append(BaseNumber(dingdian[0]))
        self.label.add("求二次函数的对称轴")
        return self


# 求二次函数的最小值
class ErCiMini(HanShuErCiDingDian):
    def solver(self, *args):
        f1 = Symbol("y")
        f2 = args[0].expression

        symbol = default_symbol(f2)
        dingdian = self.get_dingdian(f1, f2)
        if safe_degree(f2, symbol) == 2:
            f2_poly = Poly(f2.as_expr(), symbol)
            a, b, c = f2_poly.all_coeffs()
            self.output.append(BaseNumber(dingdian[1]))
            if a > 0:
                self.steps.append(["", "最小值为 %s" % new_latex(dingdian[1])])
                self.label.add("求二次函数的最小值")
            elif a < 0:
                self.steps.append(["", "最大值为 %s" % new_latex(dingdian[1])])
                self.label.add("求二次函数的最大值")
        return self


# 根据二次函数的定义求参
class HanShuErCiIs(BaseFunction):
    def solver(self, *args):
        f2 = args[0].expression
        res = ErCi003().solver(BaseEq([f2, S.Zero])).output[0]
        if isinstance(res, BaseEq) or isinstance(res, BaseIneq):
            eqs = [res.value]
        elif isinstance(res, BaseEqs) or isinstance(res, BaseIneqs):
            eqs = res.value
        self.steps.append(["由二次函数的定义得", self.output_eqs(eqs)])
        self.label.add("根据二次函数的定义求参")
        self.output.append(base_gen(eqs))
        return self


# 求二次函数的开口方向
class ErCiKaiKou(BaseFunction):
    def solver(self, *args):
        f1 = Symbol("y")
        assert str(f1) == "y", "Not a function!"
        f2 = args[0].expression.expand().simplify()
        self.steps.append(["依题意，得", BaseEq([f1, f2]).printing()])
        symbol = default_symbol(f2)
        if safe_degree(f2, symbol) == 2:
            f2_poly = Poly(f2.as_expr(), symbol)
            a, b, c = f2_poly.all_coeffs()
            if a.is_Number:
                if a > 0:
                    self.steps.append(["", "因为 %s > 0, 所以二次函数的开口向上" % (new_latex(a))])
                elif a < 0:
                    self.steps.append(["", "因为 %s < 0, 所以二次函数的开口向下" % (new_latex(a))])
        return self


if __name__ == '__main__':
    pass
